home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mint110s / context.spp < prev    next >
Text File  |  1994-01-31  |  10KB  |  300 lines

  1. ;
  2. ; Copyright 1992 Eric R. Smith
  3. ; Copyright 1992,1993 Atari Corporation
  4. ; All rights reserved.
  5.  
  6. %include "magic.i"
  7. ;
  8. ; routines for saving/restoring user contexts
  9. ;
  10. ; long build_context(struct context *sav, short fmt):
  11. ;    Called from an interrupt handler (such as the trap #1 routine
  12. ;    for system calls) saves the context of the interrupted
  13. ;    routine. Assumes that no user registers have been changed
  14. ;    since the interrupt, and that the PC and status register
  15. ;    are still on the stack. Returns the stack pointer being used
  16. ;    at the time of the interrupt **in register a1**.
  17. ;    The fmt parameter is used on the 68000 to communicate the exception
  18. ;    vector number; on >=68010 we use the vector offset from the frame.
  19. ;
  20. ; long save_context(struct context *sav):
  21. ;    Saves the context of the calling routine in the area pointed
  22. ;    to by sav. Save_context always returns 0 when initially called;
  23. ;    this is so processes can (by suitably manipulating the
  24. ;    saved registers) tell when the return from save_context is
  25. ;    actually caused by restoring the context, e.g.:
  26. ;        if (save_context(sav) == 0) {        <<-- L1
  27. ;            /* do some stuff */
  28. ;            sav.regs[D0] = 1;    /* for restore context */
  29. ;            restore_context(sav);    /* goes back to L1 */
  30. ;        }
  31. ;        else /* this is the second time through */
  32. ;
  33. ; void restore_context(struct context *sav):
  34. ;    Restores a context previously saved by build_context or save_context.
  35. ;    Since the program counter is part of the context, this function
  36. ;    will never return (it's like longjmp()). NOTE: this function should
  37. ;    be used only to change contexts _within_ the same program, since
  38. ;    it does NOT flush the ATC. See change_context
  39. ;
  40. ; void change_context(struct context *sav):
  41. ;    Restores a context previously saved by build_context or save_context
  42. ;    for a different process. Unlike restore_context, this one *does*
  43. ;    flush the ATC.
  44.  
  45.     TEXT
  46.     
  47.     XDEF    _build_context
  48.     XDEF     _save_context
  49.     XDEF    _restore_context
  50.     XDEF    _change_context
  51.  
  52.     XREF    _fpu
  53.     XREF    _framesizes
  54.     XREF    _new_trace    ; from intr.s
  55.     XREF    _no_mem_prot    
  56.  
  57.     TEXT
  58. _build_context:
  59.     move.l    a0,-(sp)    ; save a0; we'll use it for scratch
  60.     move.l    8(sp),a0    ; get address of save area
  61.  
  62.     tst.w    _no_mem_prot    ; is there memory protection?
  63.     bne.s    noprot1
  64.     pmove    crp,C_CRP(a0)    ; save CRP from MMU
  65.     pmove    tc,C_TC(a0)    ; save TC from MMU
  66. noprot1:
  67.     movem.l    d0-d7/a0-a6,(a0)    ; save registers D0-D7/A0-A6
  68.     clr.b    C_PTRACE(a0)    ; no pending traces, thanks!
  69.     lea    12(sp),a1    ; start of the interesting stack area
  70.     move.w    (a1)+,d0    ; 68000 fake frame format
  71.  
  72. %ifndef ONLY030
  73.     move.w    ($59e).w,d7    ; get process frame flag
  74.     bne.s    nojunk        ; we have some junk on the stack
  75.     move.w    d0,C_SFMT(a0)    ; save fake frame format
  76.     subq.w    #$8,d0        ; if bus error (note: subq is faster than
  77.     beq.s    group0        ; cmp, and we won't need d0 later)
  78.     subq.w    #$4,d0        ; or address error ($C==$8+$4)
  79.     bne.s    nojunk
  80. group0:    move.l    (a1)+,C_INTERNAL(a0)    ; stash it in the internal area
  81.     move.l    (a1)+,C_INTERNAL+4(a0)    ; if a debugger's interested
  82. nojunk:
  83. %endif
  84.     move.w    (a1)+,d0    ; get SR of context
  85.     move.w    d0,C_SR(a0)    ; save it
  86.     move.l    (a1)+,C_PC(a0)    ; save PC of context
  87. %ifndef ONLY030
  88.     tst.w    d7        ; test longframe (AKP)
  89.     beq.s    short1        ; short
  90. %endif
  91.     tst.w    _fpu        ; is there a true FPU in the system
  92.     beq.s    nofpu
  93.     fsave    C_FSTATE(a0)        ; save internal state frame
  94.     tst.b    C_FSTATE(a0)        ; if NULL frame then the FPU is not in use
  95.     beq.s    nofpu        ; skip programmer's model save
  96.     fmovem.x    fp0-fp7,C_FREGS(a0)        ; save data registers
  97.     fmovem.l    fpcr/fpsr/fpiar,C_FCTRL(a0)    ; and control registers
  98. nofpu:
  99.     lea    C_SFMT(a0),a2
  100.     move.w    (a1)+,d1    ; fetch frame format word
  101.     move.w    d1,(a2)+    ; and stash it away for later
  102.     lsr.w    #8,d1        ; isolate the frame format identifier
  103.     lsr.w    #4,d1
  104.     lea    _framesizes,a3
  105.     move.b    0(a3,d1.w),d1
  106.     beq.s    short1        ; if no data to save, skip this
  107.     subq.w    #1,d1        ; correct for first time through loop
  108. bcint:    move.w    (a1)+,(a2)+    ; copy CPU internal state
  109. bcover:    dbf    d1,bcint
  110. short1:
  111.     move.l    a1,C_SSP(a0)    ; a1 now points above the state frame
  112.     move.l    usp,a1        ; save user stack pointer
  113.     move.l    a1,C_USP(a0)
  114.     btst    #13,d0        ; check for supervisor mode
  115.     beq.s    L_CONT1        ; user mode; we already have stack in a1
  116. L_SUPER1:
  117. ; moving from the save state buffer 
  118. ; means not testing longframe again. (AKP)
  119.     move.l    C_SSP(a0),a1    ; was using super stack pointer before interrupt
  120.                 ; 
  121. L_CONT1:
  122.     move.l    ($408).w,C_TERM(a0) ; save GEMDOS terminate vector
  123.     move.l    (sp)+,C_A0(a0)    ; save old register a0
  124.     rts
  125.  
  126.  
  127. _save_context:
  128.     move.l    a0,-(sp)    ; save a0
  129.     move.l    8(sp),a0    ; get address of context save area
  130.  
  131.     tst.w    _no_mem_prot
  132.     bne.s    noprot2
  133.     pmove    crp,C_CRP(a0)    ; save the CRP from the MMU
  134.     pmove    tc,C_TC(a0)    ; save the TC from the MMU
  135. noprot2:
  136.  
  137. ; if running with a true coprocessor we need to save the FPU state
  138.     tst.w    _fpu        ; is there a true FPU in the system
  139.     beq.s    nofpu2
  140.     fsave    C_FSTATE(a0)        ; save internal state frame
  141.     tst.b    C_FSTATE(a0)        ; if NULL frame then the FPU is not in use
  142.     beq.s    nofpu2        ; skip programmer's model save
  143.     fmovem.x    fp0-fp7,C_FREGS(a0)        ; save data registers
  144.     fmovem.l    fpcr/fpsr/fpiar,C_FCTRL(a0)    ; and control registers
  145. nofpu2:
  146. ; note: I am somewhat unsure of this assumption, viz that save_context
  147. ; can never be called in a situation where a co-processor
  148. ; mid-instruction stack frame would be required. I suspect this is a
  149. ; valid assumption, in which case the above FPU code is redundant, the
  150. ; next line is not however!
  151.  
  152.     clr.w    C_SFMT(a0)        ; mark as a 4 word stack frame
  153.     clr.b    C_PTRACE(a0)        ; no pending traces, thanks!
  154.  
  155.     movem.l    d0-d7/a0-a6,(a0)    ; save D0-D7/A0-A6
  156.     lea    8(sp),a1
  157.     move.l    a1,C_SSP(a0)    ; save supervisor stack pointer
  158.                 ; note that it should be pointing above the PC
  159.     move.l    -4(a1),C_PC(a0)    ; save PC
  160.     move.l    usp,a1
  161.     move.l    a1,C_USP(a0)    ; save user stack pointer
  162.     move.w    sr,C_SR(a0)    ; save status register
  163.     move.l    ($408).w,C_TERM(a0)    ; save GEMDOS terminate vector
  164.     move.l    (sp)+,C_A0(a0)    ; save old a0
  165.     moveq.l    #0,d0        ; return 0
  166.     rts
  167.  
  168. _restore_context:
  169.     ori.w    #$0700,sr    ; mask interrupts
  170.     move.l    4(sp),a0    ; address of context save area
  171.  
  172. ; Switch stacks now - starting now ssp is in the memory space of
  173. ; the process we're switching to. Thus, we can change memory context
  174. ; to there.
  175.  
  176.     move.l    C_SSP(a0),a1    ; get supervisor stack pointer
  177.     tst.b    (a1)        ; touch the page for virtual memory programs
  178.     tst.b    -63(a1)    ; make sure stack can grow
  179.     move.l    a1,sp
  180.     move.l    C_USP(a0),a1
  181.     move.l    a1,usp        ; set user stack pointer
  182.     move.l    C_TERM(a0),($408).w    ; restore GEMDOS terminate vector
  183.  
  184. ; Set memory context now: actually, this isn't necessary, since
  185. ; we're coming back to a context in the same process as is running
  186. ; now.
  187. ;    tst.w    _no_mem_prot
  188. ;    bne.s    noprot3
  189. ;    pmove    C_CRP(a0),crp    ; restore MMU root pointer
  190. ;    pmove    C_TC(a0),tc    ; restore MMU control register
  191. noprot3:
  192.  
  193. %ifndef ONLY030
  194.     tst.w    ($59e).w    ; test longframe (AKP)
  195.     beq.s    short3
  196. %endif
  197. ; was moveq.l #0,d0, but I don't think that's what was desired */
  198.     moveq.l    #0,d1
  199.     lea    C_SFMT(a0),a1
  200.     move.w    (a1)+,d0    ; fetch frame format word
  201.     move.w    d0,d1        ; copy it for later
  202.     lsr.w    #8,d1        ; isolate the frame format identifier
  203.     lsr.w    #4,d1
  204.     lea    _framesizes,a2
  205.     move.b    0(a2,d1.w),d1
  206.     beq.s    rcovernc    ; if no data to copy, skip the copy
  207.     sub.w    d1,sp
  208.     sub.w    d1,sp
  209.     move.l    sp,a2
  210.     bra.s    rcover
  211.     subq.w    #1,d1        ; correct for first time through loop
  212. rcint:    move.w    (a1)+,(a2)+
  213. rcover:    dbf    d1,rcint
  214. rcovernc:
  215.     move.w    d0,-(sp)    ; frame format identifier
  216. ; if running with a true coprocessor we need to restore the FPU state
  217.  
  218.     tst.w    _fpu        ; is there a true FPU in the system
  219.     beq.s    short3
  220.     tst.b    C_FSTATE(a0)        ; if NULL frame then the FPU is not in use
  221.     beq.s    short4        ; skip programmer's model restore
  222.     fmovem.l    C_FCTRL(a0),fpcr/fpsr/fpiar    ; restore control registers
  223.     fmovem.x    C_FREGS(a0),fp0-fp7        ; and data registers
  224. short4:    frestore    C_FSTATE(a0)            ; finally the internal state
  225. short3:
  226.     move.l    C_PC(a0),-(sp)    ; push the PC
  227.     move.w    C_SR(a0),-(sp)    ; push the status register
  228.     tst.b    C_PTRACE(a0)        ; check for a pending trace
  229.     movem.l    (a0),d0-d7/a0-a6    ; restore registers d0-d7/a0-a6
  230.     beq.s    notrace
  231.     jmp    _new_trace
  232. notrace:
  233.     rte            ; jump back to old context
  234.  
  235.  
  236. _change_context:
  237.     ori.w    #$0700,sr    ; mask interrupts
  238.     move.l    4(sp),a0    ; address of context save area
  239.  
  240. ; Switch stacks now - starting now ssp is in the memory space of
  241. ; the process we're switching to. Thus, we can change memory context
  242. ; to there.
  243.  
  244.     move.l    C_SSP(a0),a1    ; get supervisor stack pointer
  245.     tst.b    (a1)        ; touch the page for virtual memory programs
  246.     tst.b    -63(a1)    ; make sure stack can grow
  247.     move.l    a1,sp
  248.     move.l    C_USP(a0),a1
  249.     move.l    a1,usp        ; set user stack pointer
  250.     move.l    C_TERM(a0),($408).w    ; restore GEMDOS terminate vector
  251.  
  252. ; Set memory context now
  253.     tst.w    _no_mem_prot
  254.     bne.s    noprot4
  255.     pmove    C_CRP(a0),crp    ; restore MMU root pointer
  256.     pmove    C_TC(a0),tc    ; restore MMU control register
  257. noprot4:
  258. %ifndef ONLY030
  259.     tst.w    ($59e).w    ; test longframe (AKP)
  260.     beq.s    short6
  261. %endif
  262. ; was moveq.l #0,d0, but I don't think that's what was desired */
  263.     moveq.l    #0,d1
  264.     lea    C_SFMT(a0),a1
  265.     move.w    (a1)+,d0    ; fetch frame format word
  266.     move.w    d0,d1        ; copy it for later
  267.     lsr.w    #8,d1        ; isolate the frame format identifier
  268.     lsr.w    #4,d1
  269.     lea    _framesizes,a2
  270.     move.b    0(a2,d1.w),d1
  271.     beq.s    rcover2nc    ; if no data to copy, skip it
  272.     sub.w    d1,sp
  273.     sub.w    d1,sp
  274.     move.l    sp,a2
  275.     subq.w    #1,d1        ; correct for first time through loop
  276. rcint2:    move.w    (a1)+,(a2)+
  277. rcover2: dbf    d1,rcint2
  278. rcover2nc:
  279.     move.w    d0,-(sp)    ; frame format identifier
  280. ; if running with a true coprocessor we need to restore the FPU state
  281.  
  282.     tst.w    _fpu        ; is there a true FPU in the system
  283.     beq.s    short6
  284.     tst.b    C_FSTATE(a0)        ; if NULL frame then the FPU is not in use
  285.     beq.s    short5        ; skip programmer's model restore
  286.     fmovem.l    C_FCTRL(a0),fpcr/fpsr/fpiar    ; restore control registers
  287.     fmovem.x    C_FREGS(a0),fp0-fp7        ; and data registers
  288. short5:    frestore    C_FSTATE(a0)            ; finally the internal state
  289. short6:
  290.     move.l    C_PC(a0),-(sp)    ; push the PC
  291.     move.w    C_SR(a0),-(sp)    ; push status register
  292.     tst.b    C_PTRACE(a0)        ; check for a pending trace
  293.     movem.l    (a0),d0-d7/a0-a6    ; restore registers d0-d7/a0-a6
  294.     beq.s    notrace2
  295.     jmp    _new_trace
  296. notrace2:
  297.     rte            ; jump back to old context
  298.  
  299.     END
  300.